package com.wlqq.ijiami

import com.google.gson.Gson
import com.google.gson.GsonBuilder
import org.apache.http.HttpStatus
import org.apache.http.client.methods.HttpGet
import org.apache.http.client.methods.HttpPost
import org.apache.http.entity.mime.HttpMultipartMode
import org.apache.http.entity.mime.MultipartEntity
import org.apache.http.entity.mime.content.FileBody
import org.apache.http.entity.mime.content.StringBody
import org.apache.http.impl.client.CloseableHttpClient
import org.apache.http.impl.client.HttpClients
import org.apache.http.protocol.HTTP
import org.apache.http.util.EntityUtils

import java.nio.charset.Charset
import java.text.DateFormat
import java.text.SimpleDateFormat
import java.util.concurrent.TimeUnit

/**
 * Created by bshao on 11/25/15.
 */
class IJiaMi {

    private static final int STATUS_OK = 1100
    private static final int STATUS_CHECKING = 1306
    private static final int MAX_WAIT_MINUTE = 3

    String userName
    String inputApk
    String outputApk
    Gson gson
    CloseableHttpClient httpClient
    int maxWaitMinute

    DateFormat dateFormat

    IJiaMi(String userName, String inputApk, String outputApk, int maxWaitMinute) {
        this.userName = userName
        this.inputApk = inputApk
        this.outputApk = outputApk
        this.maxWaitMinute = maxWaitMinute
        this.gson = GsonBuilder.newInstance().create()
        this.httpClient = HttpClients.createDefault()
        this.dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
    }

    def process() {
        def uploadApkRes = uploadApk()
        log("uploadApk, result: ${uploadApkRes}")
        if (uploadApkRes == null || uploadApkRes.code != STATUS_OK) return false

        def encryptRes = autoEncrypt(uploadApkRes.body.appId)
        log("autoEncrypt, result: ${encryptRes}")
        if (encryptRes == null || encryptRes.code != STATUS_OK) return false

        for (int i = 0; i < maxWaitMinute; i++) {

            TimeUnit.MINUTES.sleep(1)

            def getDownloadUrlRes = getDownloadUrl(encryptRes.body.appId)
            log("getDownloadUrl, result: ${getDownloadUrlRes}")
            if (getDownloadUrlRes != null) {
                if (getDownloadUrlRes.code == STATUS_OK) {
                    return downloadApk(getDownloadUrlRes.downUrl)
                }
            }
        }
        log("${maxWaitMinute} timeout")

        throw new Exception("${maxWaitMinute} timeout")
    }

    def uploadApk() {
        String apkPath = inputApk
        File apkFile = new File(apkPath)
        if (!apkFile.exists()) {
            throw new Exception("${apkPath} not exist")
        }

        HttpPost post = new HttpPost("http://116.255.254.146/operate/uploadByLocal")
        MultipartEntity entity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE, null, Charset.forName(HTTP.UTF_8))
        entity.addPart("userName", new StringBody(userName, "text/plain", Charset.forName(HTTP.UTF_8)))
        entity.addPart("file", new FileBody(apkFile))
        post.setEntity(entity)

        def response = httpClient.execute(post)
        def statusCode = response.getStatusLine().getStatusCode()

        log("status: ${statusCode}")

        if (statusCode == HttpStatus.SC_OK) {
            def content = EntityUtils.toString(response.getEntity())

            log("content: ${content}")

            return gson.fromJson(content, Resp1.class)
        }
    }

    def autoEncrypt(String appId) {
        log("autoEncrypt, appId: ${appId}")

        HttpGet get = new HttpGet("http://116.255.254.146/operate/autoEncrypt?appId=${appId}&userName=${userName}")

        def response = httpClient.execute(get)
        def statusCode = response.getStatusLine().getStatusCode()

        log("status: ${statusCode}")

        if (statusCode == HttpStatus.SC_OK) {
            def content = EntityUtils.toString(response.getEntity())

            log("content: ${content}")

            return gson.fromJson(content, Resp1.class)
        }
    }

    def getDownloadUrl(String appId) {
        log("getDownloadUrl, appId: ${appId}")

        HttpGet get = new HttpGet("http://116.255.254.146/operate/backResult?appId=${appId}&userName=${userName}")

        def response = httpClient.execute(get)
        def statusCode = response.getStatusLine().getStatusCode()

        log("status: ${statusCode}")

        if (statusCode == HttpStatus.SC_OK) {
            def content = EntityUtils.toString(response.getEntity())

            log("content: ${content}")

            return gson.fromJson(content, Resp2.class)
        }
    }

    def downloadApk(String url) {
        log("downloadApk, url: ${url}")

        def cmd = "wget -O ${outputApk} '${url}'"

        log("cmd: ${cmd}")

        cmd.execute()
    }

    def log(def msg) {
        println("${dateFormat.format(new Date())} ${msg}")
    }
}

class Resp1 {
    /**
     * appId : xxxx
     * userName : xxx
     */

    private BodyEntity body;
    /**
     * body : {"appId":"xxxx","userName":"xxx"}
     * code : 1100
     * msg : 上传成功
     */

    private int code;
    private String msg;

    public void setBody(BodyEntity body) {
        this.body = body;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public BodyEntity getBody() {
        return body;
    }

    public int getCode() {
        return code;
    }

    public String getMsg() {
        return msg;
    }

    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder("Resp1{");
        sb.append("body=").append(body);
        sb.append(", code=").append(code);
        sb.append(", msg='").append(msg).append('\'');
        sb.append('}');
        return sb.toString();
    }

    static class BodyEntity {
        private String appId;
        private String userName;

        public void setAppId(String appId) {
            this.appId = appId;
        }

        public void setUserName(String userName) {
            this.userName = userName;
        }

        public String getAppId() {
            return appId;
        }

        public String getUserName() {
            return userName;
        }


        @Override
        public String toString() {
            final StringBuilder sb = new StringBuilder("BodyEntity{");
            sb.append("appId='").append(appId).append('\'');
            sb.append(", userName='").append(userName).append('\'');
            sb.append('}');
            return sb.toString();
        }
    }
}

class Resp2 {
    /**
     * downUrl : http://xxx.xx.xx/apk
     * code : 1100
     * msg : 上传成功
     */

    private String downUrl;
    private int code;
    private String msg;

    public void setDownUrl(String downUrl) {
        this.downUrl = downUrl;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public String getDownUrl() {
        return downUrl;
    }

    public int getCode() {
        return code;
    }

    public String getMsg() {
        return msg;
    }

    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder("Resp2{");
        sb.append("downUrl='").append(downUrl).append('\'');
        sb.append(", code=").append(code);
        sb.append(", msg='").append(msg).append('\'');
        sb.append('}');
        return sb.toString();
    }
}
